package com.glsc.ngateway.common.base.utils.redis;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.*;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Repository;

import javax.annotation.PostConstruct;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit;


/**
 * 版权所有：国联证券信息技术管理部
 * 系统名称：股衍中证报送平台
 * 文件名称：IbltRedis.java
 * 创建时间：2020-11-20
 * 文件描述：Redis 工具类
 * 文件作者：张宁
 */


@Repository
public class IbltRedis {


    private static final Logger LOG = LoggerFactory.getLogger(IbltRedis.class);

    private final static Integer IBLT_CACHE_TIME = 60 * 10;

    private final static String IBLT_REDIS_PRE = "iblt";

    private RedisTemplate redisTemplate;


    private ValueOperations<String, String> valOps;

    private HashOperations<String, String, String> hashOps;


    private BoundHashOperations<String, String, String> bondOps;

    //    private
    @Autowired
    public IbltRedis(RedisTemplate redisTemplate) {
        RedisSerializer strRedisSerializer = new StringRedisSerializer();
        redisTemplate.setKeySerializer(strRedisSerializer);
        redisTemplate.setValueSerializer(strRedisSerializer);
        redisTemplate.setHashKeySerializer(strRedisSerializer);
        redisTemplate.setHashValueSerializer(strRedisSerializer);
        this.redisTemplate = redisTemplate;
    }

    @PostConstruct
    private void init() {
        valOps = redisTemplate.opsForValue();
        hashOps = redisTemplate.opsForHash();
    }

    /**
     * @param key
     * @return
     * @Descripiton 根据 key 查询最后的返回值
     */
    public Map<String, String> getHashByKey(String key) {
        Map<String, String> entries = redisTemplate.opsForHash().entries(key);
        return entries;
    }

    public String getValueByKey(String key) {
        Object result = redisTemplate.opsForValue().get(key);
        return Objects.nonNull(result) ? result.toString() : null;
    }


    public List<String> getValuesByKeys(List<String> keys) {

        List<String> dataLis = redisTemplate.opsForValue().multiGet(keys);
        return dataLis;
    }


    public List<Map<String, String>> getHashByKeys(Set<String> keys) {

        Cursor<Map.Entry<Object, Object>> cursor = redisTemplate.opsForHash().scan(keys, ScanOptions.NONE);
        while (cursor.hasNext()) {
            Map.Entry<Object, Object> entry = cursor.next();
        }

//        redisTemplate.boundHashOps(keys);
        return null;
    }

    public void getVaulesBykey(String key) {
        List<Object> values = redisTemplate.opsForHash().values(key);
    }

    /*
     * @description 模糊查询 key的个数
     * @param key
     * @return
     */
    public Integer countKeyNum(String key) {
        Set<String> keys = redisTemplate.keys(key);
        return keys.size();
    }

    /**
     * @param key
     * @return
     * @description 模糊查询 key的个数
     */
    public Set<String> getKeySets(String key) {
        Set<String> keys = redisTemplate.keys(key);
        return keys;
    }

    public Boolean deleteByKey(String key) {
        //boolean result = redisTemplate.delete(key);

        return redisTemplate.delete(key);
    }

    public void set(String key, Object value) {
        redisTemplate.opsForValue().set(key, value);
        redisTemplate.expire(key, 12, TimeUnit.HOURS);  // 设置14小时过期
    }


    public void setExpire(String key, Integer delayHours) {  // 设置key的过期时间

        redisTemplate.expire(key, delayHours, TimeUnit.HOURS); //延迟key的过期时间

    }

    public Object get(String key) {
        return redisTemplate.opsForValue().get(key);
    }

    public Object getList(String key) {
        return redisTemplate.opsForList().leftPop(key);
    }

    /**
     * key是否存在
     *
     * @return
     */
    public boolean exists(final String key) {
        boolean isExists = redisTemplate.hasKey(key);
        return isExists;
    }

    /**
     * value的长度
     *
     * @param key
     * @return
     */
    public long llen(String key) {
        return redisTemplate.boundListOps(key).size();
    }

    /**
     * lpop
     *
     * @param key
     * @return
     */
    public Object lpop(String key) {
        return redisTemplate.boundListOps(key).leftPop();
    }

    /**
     * rpop
     *
     * @param key
     * @return
     */
    public Object rpop(String key) {
        return redisTemplate.boundListOps(key).rightPop();
    }

    /**
     * lpush
     *
     * @param key
     * @return
     */
    public void lpush(String key, String value) {
        redisTemplate.boundListOps(key).leftPush(value);
    }


    public String getExpireTime(String key) {
        Long expire = redisTemplate.opsForValue().getOperations().getExpire(key);
        return null == expire ? null : String.valueOf(expire + System.currentTimeMillis() / 1000L);

    }

    @Nullable
    public long getExireTimeStamp(String key) {
        //>=0，表示剩余过期时间；
        //-1 键没设置过期时间；
        //-2 键不存在
        Long expire = redisTemplate.opsForValue().getOperations().getExpire(key);
        return expire < 0 ? expire : (expire + System.currentTimeMillis());
    }

    /**
     * 持有锁时间
     */
    private static final long DEFAULT_TIMEOUT = 30;

    /**
     * 简单redis锁，不可重入
     *
     * @param key
     * @return
     */

    public boolean lock(String key) {
        return lock(key, DEFAULT_TIMEOUT);
    }

    public boolean lock(String key, long timeout) {
        return lock(key, "lock", timeout);
    }

    public boolean lock(String key, String value, long timeout) {
        Boolean result = redisTemplate.opsForValue().setIfAbsent(key, value);
        if (result != null && result) {
            redisTemplate.expire(key, timeout, TimeUnit.SECONDS);
        }
        return result != null && result;
    }

    public boolean expire(String key, long timeout) {
        return redisTemplate.expire(key, timeout, TimeUnit.SECONDS);
    }

    public boolean unlock(String key) {
        Object lockValue = redisTemplate.opsForValue().get(key);
        if (Objects.nonNull(lockValue)) {
            redisTemplate.delete(key);
            return true;
        }
        return false;
    }
}
